(function(a) {
  if (!window.Promise) window.Promise = a.Promise;
  if (!window.Vue) {
    window.Vue = a.Vue;
  } else {
    Vue.prototype.setData = function(args) {
      if (args && typeof args == 'object') {
        for(let key in args){
          this[key] = args[key];
          //a.merge(this, args);
        }
      }
    }
  }
  if (!window.$) window.$ = a.$;
  document.getElementById('App').className = a.platform;
  if (a.platform == 'Web') {
    a.Storage.set('pxScale', 1, {
      type: 3
    });
    a.Storage.set('Theme', {
      Modal: {
        boxStyle: {
          width: '240px',
          borderRadius: '8px'
        },
        styles: {
          modalTitle: 'height:auto;font-size:18px;font-wight:bold;padding:16px;border-bottom:1px solid #f1f1f1;text-align:left;',
          modalContent: 'min-height: 0px;padding:32px;font-size:14px;',
          modalBtn: 'height:40px;line-height:40px;display:block;text-align:right;border-color:#f1f1f1;',
          modalCancel: 'padding:5px 12px;border:1px solid #ccc;margin-right:16px;border-radius:3px;cursor:pointer;',
          modalConfirm: 'padding:5px 12px;border:1px solid #ccc;margin-right:16px;border-radius:3px;cursor:pointer;'
        }
      },
      Picker: {
        pickCover: 'font-size:12px;opacity:0.01;filter:alpha(opacity=1);',
        pickBox: 'position:absolute;left:0px;top:0px;bottom:auto;width:240px;background:#ffffff;border:1px solid #ccc;border-radius:8px;',
        pickTitle: 'height:40px;line-height:40px;background:#F7FBFD;overflow:hidden;',
        titleText: 'height:40px;line-height:40px;float:left;',
        pickContent: 'height:200px;overflow:hidden;',
        pickBtn: 'cursor:pointer;float:left;width:48px;color:#03A9F4;font-size:14px;border:1px solid #F7FBFD;height:32px;line-height:32px;text-align:center;margin-top:3px;border-radius:3px;',
        btnCancel: 'margin-left:8px;',
        btnSelect: 'float:right;margin-right:8px;',
        pickItem: 'height:40px;line-height:40px;cursor:pointer;',
        Select: {
          itemHeight: 40,
          itemsHeight: 200,
          click: true
        }
      },
      SelectH5_bindType: 'mousewheel'
    }, {
      type: 3
    })
  } else {
    a.Storage.set('Theme', {}, {
      type: 3
    });
  }
  a.createCanvasContext = function(id) {
    var ctx = document.getElementById(id).getContext("2d");
    ctx.setFillStyle = function(color) {
      ctx.fillStyle = color;
    }
    ctx.draw = function() {

    }
    return ctx;
  }
  a.showToast = function(args) {
    if (typeof args == 'string') args = {
      title: args
    }
    if (a.platform == 'Web') {
      args.boxStyle = {
        borderRadius: '5px'
      }
      args.icon = 'none';
    }
    a.Toask.open(args);
  }
  a.toask = function(msg){
    a.showToast({
      title: msg,
      icon: 'none',
      duration: 3000
    })
    return new Promise(next => {
      setTimeout(next,3000)
    })
  }
  a.hideToast = function() {
    a.Toask.close();
  }
  a.showLoading = function(args) {
    args = args || {};
    args.loading = true;
    if (a.platform == 'Web') {
      args.boxStyle = {
        background: 'none',
        color: '#ccc'
      }
    }
    a.Toask.open(args);
  }
  a.showModal = function(args) {
    a.Modal.modal(args);
  }
  a.confirmx = function(msg, resolve, reject) {
    a.Modal.confirm(msg && typeof msg == 'object' ? JSON.stringify(msg) : msg, resolve, reject);
  }
  a.confirm = function(msg) {
    return new Promise((resolve, reject) => {
      a.confirmx(msg,resolve, reject)
    })
  }
  a.alertx = function(msg, next) {
    a.Modal.alert(msg && typeof msg == 'object' ? JSON.stringify(msg) : msg, next);
  }
  a.alert = function(msg) {
    return new Promise(next => {
      a.alertx(msg,next)
    })
  }
  // a.confirm = function(args) {
  //   args = args || {};
  //   args.confirmText = args.confirmButtonText;
  //   args.cancelText = args.cancelButtonText;
  //   a.Modal.modal(args);
  // }
  // a.alert = function(args) {
  //   args = args || {};
  //   args.showCancel = false;
  //   args.confirmText = args.confirmButtonText;
  //   args.cancelText = args.cancelButtonText;
  //   a.Modal.modal(args);
  // }
  a.hideLoading = function() {
    a.Toask.close();
  }
  a.getLocation = function(args) {
    args = args || {}
    navigator.geolocation.getCurrentPosition(args.success, args.fail);
  }
  a.getSystemInfoSync = function() {
    var rc = {};
    for (var key in window.screen) rc[key] = window.screen[key];
    return rc;
  }
  a.setNavigationBarTitle = function(options) {
    document.getElementsByTagName('title')[0].text = options.title;
  }
  a.$callback = function(fn) {
    try {
      var id = a.date(new Date()).only();
      window['_' + id] = function(ret) {
        fn(ret);
        delete window['_' + id];
      }
      return '_' + id;
    } catch (e) {
      return '';
    }
  }
  a.History = {
    container: document.getElementById('App'),
    _pageStack: [],
    _configs: [],
    _pageAppend: function() {},
    _defaultPage: null,
    _pageIndex: 1,
    setDefault: function(defaultPage, router) {
      var self = this;
      if (router instanceof Array) {
        router.forEach(function(v) {
          self.push(v);
        })
      }
      this._find(defaultPage, function(page) {
        self._defaultPage = page;
        self.init();
      })
    },
    setPageAppend: function(pageAppend) {
      this._pageAppend = pageAppend;
      return this;
    },
    getCurrentPage: function() {
      return this._pageStack[this._pageStack.length - 1];
    },
    stopHashChange: false,
    hash: location.hash,
    init: function() {
      var self = this;
      window.onhashchange = function() {
        self.hash = location.hash;
        if (self.stopHashChange) return false;
        var state = history.state || {};
        var url = location.hash.indexOf('#') === 0 ? location.hash.replace('#', '') : '';
        url = url.replace(/\//g,'_').replace(/^_/,'')
        self._find(url, function(page) {
          if (state._pageIndex <= self._pageIndex || self._findInStack(url)) {
            self._back(page);
          } else {
            self._go(page);
          }
        })
      }

      if (history.state && history.state._pageIndex) {
        this._pageIndex = history.state._pageIndex;
      }

      this._pageIndex--;
      var url = location.hash.indexOf('#') === 0 ? location.hash.replace('#', '') : '';
      url = url.replace(/\//g,'_').replace(/^_/,'')
      self._find(url, function(page) {
        self._go(page);
      })
    },
    param: '',
    reload: true, //刷新页面状态
    noReload: false, //强制不刷新
    load: function() { //刷新页面
      this.reload = true;
      var stack = this._pageStack[this._pageStack.length - 1];
      if (!stack) {
        return;
      }
      this._back(stack.config);
    },
    push: function(config) {
      this._configs.push(config);
      return this;
    },
    go: function(to, reload) {
      var self = this;
      this.reload = reload ? true : this.reload;
      this._find(to, function(config) {
        if (!config) {
          return;
        }
        location.hash = !self.param ? config.name : (config.name + '?' + self.param);
        if (a.isIE7 && 　self.hash != location.hash) window.onhashchange();
      })
    },
    currentPage: '',
    _go: function(config) {
      this._pageIndex++;
      history.replaceState && history.replaceState({
        _pageIndex: this._pageIndex
      }, '', location.href);
      var html = a.creatElement('div', {
        className: 'page ' + config.name,
        innerHTML: config.template
      })
      var className = html.className;
      html.className += ' slideIn';
      if (this.currentPage) this.currentPage.className = this.currentPage.className.replace(' js_display_block', '');
      this.currentPage = html;
      setTimeout(function() {
        html.className = className + ' js_show js_display_block';
      }, 200)
      this.container.appendChild(html);
      var scripts = html.getElementsByTagName('script');
      for (var i = 0; i < scripts.length; i++) {
        var code = scripts[i].innerHTML;
        html.removeChild(scripts[i]);
        html.appendChild(a.creatElement('script', {
          type: 'text/javascript',
          text: code
        }));
      }
      let styles = html.getElementsByTagName('style');
      for (let i = 0; i < styles.length; i++) {
        let styleCode = a.computStyle(styles[i].innerHTML);
        html.removeChild(styles[i]);
        html.appendChild(a.creatElement('style', {
          type: 'text/css',
          innerHTML: styleCode
        }))
      }
      this._pageAppend.call(this, html);
      this._pageStack.push({
        config: config,
        dom: html
      });
      this.reload = false;
      return this;
    },
    back: function() {
      history.back();
      if (a.isIE7) window.onhashchange();
    },
    _back: function(config) {
      var _this = this;
      this._pageIndex--;
      var stack = this._pageStack.pop();
      if (!stack) {
        return;
      }
      var url = location.hash.indexOf('#') === 0 ? location.hash.replace('#', '') : '';
      url = url.replace(/\//g,'_').replace(/^_/,'')
      var found = this._findInStack(url);
      if (this.currentPage) this.currentPage.className = this.currentPage.className.replace(' js_display_block', '');
      if (!found) {
        var html = a.creatElement('div', {
          className: 'page ' + config.name,
          innerHTML: config.template.replace('<template>', '<div id="' + config.name + '">').replace('</template>', '</div>')
        })
        var className = html.className;
        html.className += ' js_show js_display_block';
        this.currentPage = html;
        this.container.insertBefore(html, stack.dom);
        var scripts = html.getElementsByTagName('script');
        for (var i = 0; i < scripts.length; i++) {
          var code = scripts[i].innerHTML;
          html.removeChild(scripts[i]);
          html.appendChild(a.creatElement('script', {
            type: 'text/javascript',
            text: code
          }));
        }
        let styles = html.getElementsByTagName('style');
        for (let i = 0; i < styles.length; i++) {
          let styleCode = a.computStyle(styles[i].innerHTML);
          html.removeChild(styles[i]);
          html.appendChild(a.creatElement('style', {
            type: 'text/css',
            innerHTML: styleCode
          }))
        }
        this._pageStack.push({
          config: config,
          dom: html
        });
      } else {
        this.currentPage = found.dom;
        found.dom.className += ' js_display_block';
        this.container.insertBefore(found.dom, stack.dom);
      }
      if (this.reload) {
        this.container.removeChild(stack.dom);
      } else {
        stack.dom.className += ' slideOut';
        setTimeout(function() {
          _this.container.removeChild(stack.dom);
        }, 200)
      }
      this.reload = false;
      return this;
    },
    _findInStack: function(name) {
      name = name.split('?')[0];
      var found = null,
        stacks = [];
      for (var i = 0, len = this._pageStack.length; i < len; i++) {
        var stack = this._pageStack[i];
        if (stack.config.name === name) {
          if (stack.config.reload || this.reload) {
            this.container.removeChild(stack.dom);
          } else {
            found = stack;
            stacks.push(stack);
          }
        } else {
          stacks.push(stack);
        }
      }
      this._pageStack = stacks;
      if (name == '') found = this._pageStack[0];
      return found;
    },
    ajaxPage: function(name, flog, fn) {
      var self = this,
        page = null,
        url = flog === false ? name.replace(new RegExp('_', 'g'), '/') + '.html' : this._configs[flog].url;
        if(url.charAt(0) == '/') {
          url = location.origin + location.pathname.replace('/index.html','') + url
        }
        var ajax = new a.Ajax(url, function(html, err) {
        if (!err) {
          html = html.replace(/^<template>/,`<div id="${name}" class="scroll" style="height:100%;display:none;">`);
          let lastIndex = html.lastIndexOf('</template>');
          html = html.substr(0,lastIndex) + '</div>' + html.substring(lastIndex + 11,html.length - 1);
          html = html.replace('G.vue({',`G.vue("${name}",{`);
          if(/<style(.+)scoped.*>/.test(html)){
            html = html.replace(/\.(\w+){/gim, '#' + name + ' ' + ' .$1{').replace(/,\.(\w+){/gim, ',#' + name + ' ' + ' .$1{');
            html = html.replace(new RegExp('#' + name + ' .Web', 'gmi'), '.Web #' + name);
            html = html.replace(/rpx/gmi, 'px').replace(/^page(.*){|\spage(.*){/gi, '$1{');
            html = html.replace(/<style(.+)scoped.*>/,`<style id="page_style_${name}" scoped>`)
          }
          if (flog === false) {
            page = {
              name: name,
              url: url,
              template: html
            };
            self.push(page);
          } else {
            self._configs[flog].template = html;
            page = self._configs[flog];
          }
        } else {
          page = self._defaultPage;
        }
        fn.call(self, page);
      }, {
        dataType: 'html',
        noLoginAction: true,
        noBeforeLoginAction: true
      });
      ajax.action();
    },
    getParam: function(name) {
      var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"),
        r = this.param ? this.param.match(reg) : '';
      if (r && r[2]) return decodeURIComponent(r[2]);
      return null;
    },
    _find: function(name, fn) {
      this.param = name.split('?')[1];
      var name = name.split('?')[0],
        self = this,
        page = null;
      if (self._defaultPage && name == '') {
        fn.call(self, self._defaultPage);
      } else {
        var flog = false;
        for (var i = 0, len = this._configs.length; i < len; i++) {
          if (this._configs[i].name === name) {
            page = this._configs[i];
            flog = i;
            break;
          }
        }
        if (!page || !page.template) {
          this.ajaxPage(name, flog, function(_page) {
            fn.call(self, _page);
          })
        } else {
          fn.call(self, page);
        }
      }
    },
    home: function() {
      location.hash = this._defaultPage.name;
      if (a.isIE7) window.onhashchange();
    }
  }
  Vue.prototype.selectComponent = function(id) {
    let ref = this.$refs[id.replace('#', '')];
    return (ref instanceof Array) ? ref[0] : ref;
  }
  Vue.prototype.getData = function(key) {
    return typeof this[key] == 'object' && this[key] ? a.clone(this[key], true) : this[key];
  }
  Vue.prototype.computStyle = function(styleString,args){
    return a.computStyle(styleString,args);
  }
  Vue.prototype.on = function(event,type,method,args){
    var _this = this;
    if(!event.srcElement['bind' + method]){
      event.srcElement['bind' + method] = true;
      var ons = a.on(event.srcElement,type,function(event){
        if(typeof _this[method] == 'function') _this[method].apply(_this,event,args);
      })
      if(ons && ons[0] && typeof ons[0] == 'function') ons[0](event);
    }
  }

  if (!window.Storage) {
    a.Storage.setLocalStorage({
      setItem: function(key, value) {
        a.Cookie.Set(key, value, 10, '/');
      },
      getItem: function(key) {
        return a.Cookie.Get(key);
      },
      removeItem: function(key) {
        a.Cookie.Delete(key);
      }
    })
  }
  a.$go = function(url, openType) {
    if (openType == 'navigateBack' || url == -1) {
      history.go(-1)
    }else if(url === 0){
      history.go(0)
    }else if(url === 1){
      history.go(1)
    } else {
      if(/^live/.test(url) || /^miniApp/.test(url)){
        a.alertx('请使用小程序端打开!')
      }else if(/^http/.test(url)){
        try{
          window.open.apply(null,arguments)
        }catch(e){
          console.log('非浏览器环境，打开页面出错')
        }
      }else{
        url = typeof url == 'string' ? url : url.url;
        a.History.go(url, true);
      }
    }
  }
  a.reEnter = function(options) {
    a.History.stopHashChange = true;
    location.hash = options.replace(/\//g, '_').replace('_', '');
    location.reload();
  }
  var VueComponents = {};
  a.usingComponents = function(config) {
    config = config || {};
    if (config[a.platform]) a.merge(config, config[a.platform]);
    config.usingComponents = config.usingComponents || {};
    var usingComponents = [],
      count = 0;
    for (var key in config.usingComponents) {
      (function(key) {
        usingComponents[count] = JSONP(key.toLowerCase(), config.usingComponents[key]);
        count++;
      })(key)
    }
    return usingComponents;
  }

  function JSONP(key, path) {
    return new Promise(function(resolve, reject) {
      if (VueComponents[key]) {
        resolve();
      } else {
        VueComponents[key] = true;
        var name = path.replace(/\//g, '_').replace('_', '');
        window[name] = function(config, component) {
          component = component || {};
          var watch = {};
          if (component.props) {
            for (var k in component.props) {
              if (component.props[k].observer) watch[k] = component.props[k].observer;
            }
          }
          component.methods = component.methods || {};
          component = a.common.call(a, component, 'component');
          component.methods.triggerEvent = function(meth, detail) {
            this.$emit(meth, {
              type: meth,
              detail: detail
            });
          }
          component.watch = watch;
          var template = document.getElementById('TEMPLATE' + name);
          component.template = template.innerHTML;
          a.body.removeChild(template);
          VueComponents[key] = component;
          if (!component.data || typeof component.data != 'function') component.data = function() {
            return {}
          };
          Vue.component(key, component);
          Promise.all(a.usingComponents(config)).then(function() {
            if (!config.noCss) {
              a.computCSS(path.replace('/', '') + '.css', function() {
                window[name] = null;
                resolve();
              }, {
                id: 'componentCSS',
                replace: function(ret) {
                  if (/scoped/.test(ret)) {
                    //ret = ret.replace(/#(.+){/gim, '.' + name + ' ' + ' #$1{').replace(/,#(.+){/gim, ',.' + name + ' ' + ' #$1{');
                    //ret = ret.replace(/\.(\w+){/gim, '.' + name + ' ' + ' .$1{').replace(/,\.(\w+){/gim, ',.' + name + ' ' + ' .$1{');
                    ret = ret.replace(new RegExp('.' + name + ' .Web', 'gmi'), '.Web .' + name);
                    ret = ret.replace(new RegExp('.' + name + ' .iOS', 'gmi'), '.iOS .' + name);
                    ret = ret.replace(new RegExp('.' + name + ' .Android', 'gmi'), '.Android .' + name);
                    ret = ret.replace(/rpx/gmi, 'px').replace(/^page|\spage/gmi, '');
                    ret = ret.replace(/@import\s[^;]+;/g,'').replace('/* scoped */','');
                  }
                  return ret;
                }
              })
            } else {
              window[name] = null;
              resolve();
            }
          })
        }

        var ajax = new a.Ajax('.' + path + '.html?_=' + new Date().getTime(), function(html, err) {
          if (!err) {
            a.creatElement('div', {
              id: 'TEMPLATE' + name,
              style: {
                display: 'none'
              },
              innerHTML: html.replace('<template>', '<div class="' + name + '">').replace('</template>', '</div>'),
              parent: true
            })
            a.creatElement('script', {
              attr: {
                type: 'text/javascript',
                src: '.' + path + '.js?_=' + new Date().getTime()
              },
              id: 'JSONP' + name,
              parent: true
            })
          }
        }, {
          dataType: 'html',
          noLoginAction: true
        });
        ajax.action();
      }
    })
  }
  a.App = function(config, args) {
    args = a.common.call(a, args, 'app');
    if(args.onError) window.onerror = args.onError;
    function launch(){
      //登录
      a.Storage.set('AppConfig', config, 2);
      a.Storage.set('logined', false, 2);
      var options = {},query = a.History.param;
      if (query) {
        query = decodeURI(query).split('&');
        for (var i = 0; i < query.length; i++) {
          var key = query[i].split('=')[0];
          options[key] = query[i].replace(new RegExp(key + '='), '');
        }
      }
      if (args.init) args.init(options);
      var afters = new a.Item();
      afters._push(function(_next) {
        if (args.onLaunch) args.onLaunch(options);
        _next();
      })
      var autoLogin = function(next) {
        if (a.Storage.get('logined', 2)) {
          afters = new a.Item();
          a.Storage.set('logined', false);
        }
        afters._push(function(_next) {
          next();
          _next();
        })
        args.autoLogin(function() {
          afters._do();
          a.Storage.set('logined', true);
        }, function(error) {
          afters = new a.Item();
          if (!a.Storage.get('logined')) {
            afters._push(function(_next) {
              if (args.onLaunch) args.onLaunch(options);
              _next();
            })
          }
          a.reEnter(args.onLogin ? args.onLogin : '/pages/err/err?msg=' + error);
        })
      }
      a.Storage.set('autoLogin', autoLogin, 2);
      //ajax拦截
      if (args.Interceptor) a.Storage.set('loginAction', args.Interceptor, {
        type: 2
      });
      config.Web = config.Web || {};
      config.Web.defaultPage = config.Web.defaultPage || config.pages[0] || 'pages/index/index';
      a.computCSS('./css/style.css', function() {
        a.computCSS('./css/common.css', function() {
          a.computCSS('./css/app.css', function() {
            a.History.setDefault(config.Web.defaultPage.replace(/\//g, '_'));
          })
        })
      })
    }
    var cloudenv = a.Storage.get('cloudenv');
    if(cloudenv){
      cloud.init(cloudenv).then(launch);
    }else{
      launch();
    }
  }
  a.vue = function(id, config, args) {
    config = config || {};
    args = args || {};
    args.methods = args.methods || {};
    args = a.common.call(a, args, 'vue');
    args.el = '#' + id;
    args.components = args.components || {};
    var options = {};
    var created = args.created;
    args.created = function(){
      this.data = this._data;
      var _this = this, query = a.History.param;
      if (this['onPullDownRefresh']) a.Storage.set('onPullDownRefresh_' + id, this['onPullDownRefresh']);
      //监听页面上拉
      var currentPage = a.History.getCurrentPage();
      var onReachBottomTimer = 0;
      if(a.platform != 'Web'){
        a.on(document.getElementById(id), 'scroll', function(event) {
          currentPage.dom._scrollTop = this.scrollTop;
          if (typeof _this['onReachBottom'] == 'function' && !onReachBottomTimer && this.scrollHeight - this.scrollTop - this.offsetHeight < 50) {
            _this['onReachBottom']();
            onReachBottomTimer = setTimeout(function() {
              clearTimeout(onReachBottomTimer);
              onReachBottomTimer = 0;
            }, 3000)
          }
        })
      }
      if (query) {
        query = decodeURI(query).split('&');
        for (var i = 0; i < query.length; i++) {
          var key = query[i].split('=')[0];
          options[key] = query[i].replace(new RegExp(key + '='), '');
        }
      }
      if(created) login(this,created);
    }
    var mounted = args.mounted;
    args.mounted = function() {
      if(mounted || (!created && !mounted)) login(this,mounted);
    }
    function login(_this,meth){
      setTimeout(function() {
        if (args.noLogin || a.Storage.get('logined')) {
          if (meth) meth.call(_this, options);
        } else {
          a.Storage.get('autoLogin')(function() {
            if (meth) meth.call(_this, options);
          })
        }
      }, 300)
    }
    Promise.all(a.usingComponents(config)).then(()=>{
      return new Promise((next)=>{
        if(!document.querySelector('#page_style_' + id)){
          a.computCSS(id.replace(/_/g, '/') + '.css', next, {
            storageName: 'css_' + id,
            parent: document.getElementById(id).parentNode,
            id: 'css_' + id,
            replace: function(ret) {
              if (/scoped/.test(ret)) {
                ret = ret.replace(/\.(\w+){/gim, '#' + id + ' ' + ' .$1{').replace(/,\.(\w+){/gim, ',#' + id + ' ' + ' .$1{');
                ret = ret.replace(new RegExp('#' + id + ' .Web', 'gmi'), '.Web #' + id);
                ret = ret.replace(/rpx/gmi, 'px').replace(/^page|\spage/gmi, '');
              }
              return ret;
            }
          })
        }else{
          next()
        }
      }).then(()=>{
        document.getElementById(id).style.display = 'block';
        new Vue(args);
        a.setNavigationBarTitle({
          title: config.navigationBarTitleText || a.Storage.get('AppConfig').navigationBarTitleText || ''
        });
      })
    })
    Promise.all(a.usingComponents(config)).then(function() {
      
    })
  }
  a.ajax = function(url, callback, args) {
    args = args || {};
    var _this = this;
    if(args.loading === false) args.loading = {}
    args.loading = args.loading || {
      open: function() {
        if (a.showLoading) a.showLoading();
        if (_this.setData) _this.setData({
          submiting: true
        });
      },
      close: function() {
        if (_this.setData) {
          setTimeout(function() {
            if (a.hideLoading) a.hideLoading();
            _this.setData({
              submiting: false
            });
          }, 5000)
        } else {
          if (a.hideLoading) a.hideLoading();
        }
      }
    };
    if(a.Storage.get('tcbEnvId') && !args.UNTCB && a.cloud) {
      a.cloud.ajax(url, callback, args);
      return false;
    }
    url = url.replace(new RegExp('^{(.+)}', 'g'), function($0, $1) {
      return a.Storage.get($1) || ('{' + $1 + '}');
    })
    if (url.indexOf('http') != 0) url = a.Storage.get('APIURL') + url;
    var ajax = new a.Ajax(url, function(ret) {
      if (args.errNotify !== false && ret.errorMsg) a.showToast(ret.errorMsg);
      callback(ret);
    }, args);
    ajax.action();
  }
  a.list = function(args) {
    args = args || {};
    if(a.Storage.get('tcbEnvId') && !args.UNTCB && a.cloud) {
      return a.cloud.list(args);
    }
    var url = '',getArgs = args.get || '';
    if (typeof getArgs == 'string') {
      url = getArgs;
      getArgs = {};
    } else {
      url = getArgs.url;
      getArgs.url = undefined;
    }
    if(typeof url == 'string'){
      url = url.replace(new RegExp('^{(.+)}', 'g'), function($0, $1) {
        return a.Storage.get($1) || ('{' + $1 + '}');
      })
      if (url.indexOf('http') != 0) url = a.Storage.get('APIURL') + url;
      args.get = new a.Ajax(url, '', getArgs);
    }
    return new a.List(args);
  }
  //全局监听下拉刷新
  var onPullDownRefreshStart = 0, PullDownRefresh = document.getElementById('PullDownRefresh');
  a.canPullDownRefresh = true;
  a.on(window, 'touchstart', function(event) {
    if (onPullDownRefreshStart > 0) a.stopPullDownRefresh();
    var startY = 0;
    for (var i = 0; i < event.changedTouches.length; i++) {
      if (!startY || event.changedTouches[i].clientY < startY) startY = event.changedTouches[i].clientY;
    }
    var currentPage = a.History.getCurrentPage();
    if (a.canPullDownRefresh && !onPullDownRefreshStart && !currentPage.dom._scrollTop && typeof a.Storage.get('onPullDownRefresh_' + currentPage.config.name) == 'function') {
      onPullDownRefreshStart = startY;
      PullDownRefresh.innerHTML = '<span>释放刷新</span>';
    }
  })
  a.on(window, 'touchmove', function(event) {
    var moveY = 0;
    for (var i = 0; i < event.changedTouches.length; i++) {
      if (event.changedTouches[i].clientY > moveY) moveY = event.changedTouches[i].clientY;
    }
    if (onPullDownRefreshStart > 0 && moveY - onPullDownRefreshStart > 0) {
      PullDownRefresh.style.height = (moveY - onPullDownRefreshStart) / 3 + 'px';
    }
  })
  a.on(window, 'touchend', function(event) {
    var endY = 0;
    for (var i = 0; i < event.changedTouches.length; i++) {
      if (event.changedTouches[i].clientY > endY) endY = event.changedTouches[i].clientY;
    }
    if (onPullDownRefreshStart > 0) {
      if (endY - onPullDownRefreshStart > 100) {
        a.Storage.get('onPullDownRefresh_' + a.History.getCurrentPage().config.name)();
        PullDownRefresh.innerHTML = '<span>刷新中...</span>';
      }
    }
  })
  a.stopPullDownRefresh = function() {
    PullDownRefresh.style.height = '0px';
    onPullDownRefreshStart = 0;
    PullDownRefresh.innerHTML = '';
  }
  a.location = function() {
    return '/' + location.hash.replace('#','').split('?')[0].replace(/_/g, '/');
  }
  a.common.call(a);
  Vue.component('icon', {
    template: '<i :style="styles" :class="classes"></i>',
    props: ['type', 'size', 'color'],
    data: function() {
      return {
        classes: {
          'icon-info': false,
          'icon-warn': false,
          'icon-waiting': false,
          'icon-cancel': false,
          'icon-download': false,
          'icon-search': false,
          'icon-clear': false,
          'icon-success': false,
          'icon-success-no-circle': false
        },
        styles: {
          fontSize: '',
          color: '',
          position: 'relative',
          top: '3px'
        }
      }
    },
    created: function() {
      this.styles.color = this.color || '#666';
      this.styles.fontSize = (this.size || 46) + 'px';
      this.type = (this.type || 'info').replace(/_/g, '-');
      this.classes['icon-' + this.type] = true;
    }
  });
  Vue.component('navigator', {
    template: '<span @click="$go"><slot></slot></span>',
    props: ['openType', 'url'],
    methods: {
      $go: function() {
        a.$go(this.url, this.openType);
      }
    }
  })
  Vue.component('switch_', {
    template: '<span><input v-model="checked" :disabled="disabled" type="checkbox" @change="_change" /><slot></slot></span>',
    props: ['checked', 'type', 'disabled', 'color'],
    methods: {
      _change: function() {
        this.$emit('change', {
          type: 'change',
          detail: {
            value: !!this.checked
          }
        });
      }
    }
  })
  Vue.component('favorite', {
    template: '<div></div>'
  })
  Vue.component('button_', {
    props: ['type', 'size', 'disabled'],
    template: '<span :class="classes" @click="_click"><slot></slot></span>',
    data: function() {
      var classes = '';
      classes += ' button';
      var type = this.type || 'primary';
      classes += ' ' + type;
      if (this.size === 'mini') classes += ' mini';
      if (this.disabled) classes += ' disabled';
      return {
        classes: classes
      }
    },
    methods: {
      _click: function() {
        this.$emit('click')
      }
    }
  })
})(Y)